﻿using BluetoothMachine.Enums;
using BluetoothMachine.Lucifer;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace BluetoothMachine.DeviceCommunications
{
    /// <summary>
    /// TCP通信
    /// </summary>
    public class CommTCP : ICommunication
    {
        public CommTCP()
        {
            ByteBuffer = new List<byte>();
        }
        public CommTCP(string address, int port) : this()
        {
            _address = address;
            _port = port;
        }
        private string _address;
        private int _port;
        private Socket _socket;
        public int Index { get; set; }
        public DeviceType Types { get; set; }
        public bool CommType { get; set; }
        public List<byte> ByteBuffer { get; set; }
        private System.Threading.CancellationTokenSource _tokenSource;

        public void Connection()
        {
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _socket.SendTimeout = 10000;
            _socket.ReceiveTimeout = 10000;
            _socket.ReceiveBufferSize = 2048;
            _socket.SendBufferSize = 1024;
            _socket.Connect(IPAddress.Parse(_address), _port);
            _tokenSource = new System.Threading.CancellationTokenSource();
            
        }

        public void Disconnect() { if (_socket != null) _socket.Close(); _tokenSource.Cancel(); }

        public void Read(object obj = null)
        {
            Task.Run(() =>
            {
                byte[] bytes = new byte[2048];
                while (true)
                {
                    try
                    {
                        int length = _socket.Receive(bytes, 0, 2048, SocketFlags.None);
                        ByteBuffer.AddRange(bytes.Take(length).ToArray());
                    }
                    finally
                    { }
                    if (_tokenSource.Token.IsCancellationRequested)
                    {
                        ByteBuffer.Clear();
                        return;
                    }
                }
            }, _tokenSource.Token);
        }

        public byte[] Read()
        {
            byte[] bytes = new byte[2048];
            int length = _socket.Receive(bytes, 0, 2048, SocketFlags.None);
            return bytes.Take(length).ToArray();
        }

        public T ReadClass<T>(IProtocol protocol) where T : new()
        {
            return new T();
        }

        public T ReadClass<T>(object obj)
        {
            return (T)new object();
        }

        public void Write(byte[] bytes)
        {
            log4net.LogManager.GetLogger("message").Warn($"控制协议：{BitConverter.ToString(bytes)}\r\n");
            _socket.Send(bytes, 0, bytes.Length, SocketFlags.None);
        }

        public void Write(IProtocol protocol)
        {
            Write(protocol.GetStream());
        }
    }
}
